package com.cml.dm.admin.service.impl;

import cn.hutool.core.io.IoUtil;
import com.cml.dm.admin.service.FileCompressFactory;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

@Component
public class ZipCompressProcessor implements FileCompressFactory {

    private static Logger logger = LoggerFactory.getLogger(ZipCompressProcessor.class);

    @Override
    public String compress(InputStream is, String name, String zipFilePath) {
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        int count = 1024;
        try {
            byte[] bytes = new byte[count];
            File zipFile = new File(zipFilePath);
            if(zipFile.exists()){
                throw new RuntimeException("压缩文件已存在");
            }
            fos = new FileOutputStream(zipFile);
            zos = new ZipOutputStream(fos);
            ZipEntry zipEntry = new ZipEntry(name);
            zos.putNextEntry(zipEntry);
            BufferedOutputStream bos = new BufferedOutputStream(zos);
            int len = 0;
            while (-1 != (len = is.read(bytes))){
                bos.write(bytes,0,len);
            }
            bos.flush();
            zos.flush();
            bos.close();
            return zipFilePath;
        }catch (Exception e){
            logger.error("压缩文件失败",e);
            throw new RuntimeException("压缩文件失败");
        }finally {
            IoUtil.close(zos);
            IoUtil.close(fos);
        }
    }

    @Override
    public String compress(byte[] bytes, String name, String zipFilePath) {
        FileOutputStream fos = null;
        ZipOutputStream zos = null;
        try {
            File zipFile = new File(zipFilePath);
            if(zipFile.exists()){
                throw new RuntimeException("压缩文件已存在");
            }
            fos = new FileOutputStream(zipFile);
            zos = new ZipOutputStream(fos);
            ZipEntry zipEntry = new ZipEntry(name);
            zos.putNextEntry(zipEntry);
            BufferedOutputStream bos = new BufferedOutputStream(zos);
            bos.write(bytes);
            bos.flush();
            zos.flush();
            bos.close();
            return zipFilePath;
        }catch (Exception e){
            logger.error("压缩文件失败",e);
            throw new RuntimeException("压缩文件失败");
        }finally {
            IoUtil.close(zos);
            IoUtil.close(fos);
        }
    }

    @Override
    public List<String> uncompress(String filePath) {
        BufferedOutputStream bos = null;
        FileOutputStream fos = null;
        ZipInputStream zis = null;
        FileInputStream fis = null;
        int count = 1024;
        List<String> paths = new ArrayList<>();
        try {
            File zipFile = new File(filePath);
            String savePath = zipFile.getParent()+File.separator;
            fis = new FileInputStream(zipFile);
            zis = new ZipInputStream(fis);
            ZipEntry entry;

            while ((entry = zis.getNextEntry()) != null) {

                int size;
                byte[] buffer = new byte[count];
                File fileOut = new File(savePath+entry.getName());
                paths.add(fileOut.getPath());
                fos = new FileOutputStream(fileOut);
                bos = new BufferedOutputStream(fos, buffer.length);
                while ((size = zis.read(buffer, 0, buffer.length)) != -1) {
                    bos.write(buffer, 0, size);
                }
                bos.flush();
                fos.flush();
            }
            return paths;
        }catch (Exception e){
            logger.error("解压缩文件失败：",e);
            throw new RuntimeException("解压缩文件失败");
        }finally {
            IoUtil.close(bos);
            IoUtil.close(fos);
            IoUtil.close(zis);
            IoUtil.close(fis);
        }
    }
}
